package edu.joe.game.solvers;

import edu.joe.game.ParticleData;
import edu.joe.game.ParticleMotionSolver;
import edu.joe.game.ParticlePhysicsModel;

public class NBodySolver extends ParticleMotionSolver {

	public NBodySolver(ParticleData[] particles, ParticlePhysicsModel physics) {
		super(particles, physics);
	}

	@Override
	public void update(double dt) {
		for (int i = 0; i < super.particles.length; i++) {
			ParticleData particle1 = super.particles[i];
			if (particle1.life > 0) {
				particle1.life -= dt;
				particle1.x += particle1.dx * dt;
				particle1.y += particle1.dy * dt;
				particle1.z += particle1.dz * dt;

				particle1.dx *= this.physics.velocityDamp;
				particle1.dy *= this.physics.velocityDamp;
				particle1.dz *= this.physics.velocityDamp;

				particle1.dx += particle1.fx * dt;
				particle1.dy += particle1.fy * dt + this.physics.gravity * dt;
				particle1.dz += particle1.dz * dt;

				particle1.fx *= this.physics.velocityDamp;
				particle1.fy *= this.physics.velocityDamp;
				particle1.fz *= this.physics.velocityDamp;
				for (int j = 0; j < super.particles.length; j++) {
					if (i != j) {
						ParticleData particle2 = super.particles[j];
						// update particle 1, check velocities and positions

						if (particle2.life > 0) {
							double lx = particle2.x - particle1.x;
							double ly = particle2.y - particle1.y;
							double lz = particle2.z - particle1.z;
							double mag = 1.0 / Math.sqrt(lx * lx + ly * ly + lz
									* lz);
							double nx = lx * mag;
							double ny = ly * mag;
							double nz = lz * mag;
							double r = particle2.w * particle2.h;
							if (lx * lx + ly * ly + lz * lz < r) {
								// intersection
								double pnx = particle1.x - particle2.x;
								double pny = particle1.y - particle2.y;
								double pnz = particle1.z - particle2.z;
								double nmag = 1.0 / Math.sqrt(pnx * pnx + pny
										* pny + pnz * pnz);
								pnx *= nmag;
								pny *= nmag;
								pnz *= nmag;
								double vdn = (particle1.dx * pnx + particle1.dy
										* pny + particle1.dz * pnz);
								double bx = vdn * pnx;
								double by = vdn * pny;
								double bz = vdn * pnz;

								particle1.dx = particle1.dx - bx
										- physics.bounceFactor * bx;
								particle1.dy = particle1.dy - by
										- physics.bounceFactor * by;
								particle1.dz = particle1.dz - bz
										- physics.bounceFactor * bz;
								particle1.x = particle2.x + lx * (mag + 0.01);
								particle1.y = particle2.y + ly * (mag + 0.01);
								particle1.z = particle2.z + lz * (mag + 0.01);

							}
						}
					}
				}
			}
		}
	}
}
